package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.Constant.OrderConstant;
import com.hmall.common.clients.ItemClient;
import com.hmall.common.clients.UserClient;
import com.hmall.common.dto.Address;
import com.hmall.common.dto.OrderDTO;
import com.hmall.common.dto.User;
import com.hmall.common.utils.BaseThreadLocal;
import com.hmall.common.utils.SnowFlakeUtil;
import com.hmall.common.vo.ItemVo;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.service.IOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    UserClient userClient;
    @Autowired
    ItemClient itemClient;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    OrderLogisticsMapper orderLogisticsMapper;
    @Autowired
    RabbitTemplate rabbitTemplate;
    private static final String DIRECT_NAME = "delay.direct";
    private static final String ROUTING_KEY = "delay";
    /**
     * 提交订单
     *
     * @param orderDTO
     * @return
     */
    @Override
    @GlobalTransactional
    public String createOrder(OrderDTO orderDTO) {
        if (orderDTO == null) {
            return null;
        }
        //1.封装订单信息
        Order order = new Order();
        //使用雪花算法工具类生成订单id
        order.setId(SnowFlakeUtil.getDefaultSnowFlakeId());
        //设置订单创建时间
        order.setCreateTime(new Date());
        //设置付款方式
        order.setPaymentType(orderDTO.getPaymentType());
        //根据itemId查询商品信息
        ItemVo itemVo = itemClient.findById(orderDTO.getItemId());
        if (itemVo == null) {
            return null;
        }
        //根据商品价格和购买数量计算总价
        order.setTotalFee(itemVo.getPrice() * orderDTO.getNum());
        //设置状态为待付款
        order.setStatus(OrderConstant.PENDING_PAYMENT);
        //设置userId
        order.setUserId(BaseThreadLocal.getUserId());
        //添加订单至数据库
        orderMapper.insert(order);
        
        //2.封装订单详情
        OrderDetail orderDetail = new OrderDetail();
        //设置orderId
        orderDetail.setOrderId(order.getId());
        //设置创建时间
        orderDetail.setCreateTime(new Date());
        //设置购买数量
        orderDetail.setNum(orderDTO.getNum());
        //设置商品图片
        orderDetail.setImage(itemVo.getImage());
        //设置商品id
        orderDetail.setItemId(orderDTO.getItemId());
        //设置商品名
        orderDetail.setTitle(itemVo.getName());
        //设置商品价格
        orderDetail.setPrice(itemVo.getPrice());
        //设置商品规格
        orderDetail.setSpec(itemVo.getSpec());
        //添加订单详情至数据库
        orderDetailMapper.insert(orderDetail);
        
        //3.封装订单收货人
        OrderLogistics orderLogistics = new OrderLogistics();
        //feign根据地址id获取地址信息
        Address address = userClient.findAddressById(orderDTO.getAddressId());
        if (address == null){
            return null;
        }
        //设置手机号
        orderLogistics.setPhone(address.getMobile());
        //设置订单id
        orderLogistics.setOrderId(order.getId());
        //将地址数据拷贝
        BeanUtils.copyProperties(address, orderLogistics);
        //设置创建时间
        orderLogistics.setCreateTime(new Date());
        //添加收货人信息至数据库
        orderLogisticsMapper.insert(orderLogistics);
        
        //4.削减库存
        itemClient.reduceStock(orderDTO.getItemId(), orderDTO.getNum());
    
        //5.发送订单id和超时时间30分钟至延迟队列
        Message msg = MessageBuilder.withBody(order.getId().toString().getBytes(StandardCharsets.UTF_8))
                .setHeader("x-delay",1800000)
                .build();
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(DIRECT_NAME,ROUTING_KEY,msg,correlationData);
        return order.getId().toString();
    }
}
